<?php
ArrowController::importModel("org.arrowplatform.model.ArrowDataSource");
ArrowController::importModel("org.arrowplatform.controls.common.criteria.IArrowCriteriaUser"); 
ArrowController::importModel("smarty.SmartyCompiler");
ArrowController::importModel("org.arrowplatform.model.ArrowModel");
class ArrowTable extends ArrowTagContainer implements IArrowCriteriaUser{
	
	protected $dataSource;
	protected $fields;
	protected $sortField = false;
	protected $sortDir = false;
	protected $criteria;
	protected $sortable;
	protected $currentPage = false;
	protected $onPage = false;
	protected $selectable = 0;
	protected $model = 0;
	protected $debugMode = false;
	protected $debugData;
	
	
	private $list = array();
	/*
	 * Model actions
	 * 
	 * @var IArrowModelAction
	 */
	private $modelActions = array();
	
	/*
	 * Top actions
	 * 
	 * @var IArrowModelAction
	 */
	private $topActions = array();
	
	/*
	 * Row actions
	 * 
	 * @var IArrowModelAction
	 */
	private $rowActions = array();

	/*
	 * Footer actions
	 * 
	 * @var IArrowModelAction
	 */
	private $footerActions = array();
	
	/**
	 * Count of all rows
	 * @var int
	 */
	private $allRowsCount = array();
	
	/***
	    AccessModel jest wykorzystywany tylko podczas sprawdzania uprawnie
    	domyślnie jak nie jest zdefiniowany przyjmuje model
	*/
	private $searchFields;
	
	private $rowExtensibleTemplate = null;
	
	private $searchTemplate = null;
	
	private $defautlRowClass;
	private $rowClassMap; 
	
	private $footerTemplate = null ;
	private $lastFooterTemplate = null ;
	
	private $topBasePanelTemplate = null;
	private $topExtendedPanelTemplate = null;
	private $gruppingTemplate = null;
	
	public function configure(){
		$this->addProperties(array(
			"dataSource" => false,
			"dsFactory" => false,
			"zebra" => 1,
			"getPrefix" => false,
			"onPage" => 25,
			"page" => 0,
			"initiated" => 1,
			"selectable" => true,
			"sortable" => true,
			"model" => false,
			"accessModel" => false,
			"search" => null,
			"showModelActions" => false,
			"criteria" => false,
			"class" => false,
			"sort" => false,
			"sortDir" => "asc",
			"num" => false,
			"title" => false,
			"selected" => array(),
			"name" => false,
			"displaytype" => "table",
			"clearCriteria" => 1,
			"processResult" => false,
			"style" => false,
			"searchAreaExpanded" => 0,
			"filtersRegistry" => "",
			"header" => 1,
			"footer" => 1,
			"chosen" => "",
			"getRowClassDelegate" => false,
			"beforeFiltersDelegate" => false,
			"countDelegate" => false,  
			"grupping" => false,
			"debugMode" => false,
			"layout" => "normal" // normal,compact, minimal
		));
		$this->addStateProperties(array( "initiated", "onPage", "page", "selectable","sort", "selected", "search", "searchAreaExpanded", "filtersRegistry", "contextId", "chosen"));
		
	}
	
	public function setDataSource( IArrowDataSource $dataSource ){
		$this->dataSource = $dataSource;
	}
	
	public function setCriteria(  $criteria ){
		$_SESSION[self::CTRL_NAMESPACE][$this->getGlobalId()] = serialize($criteria);
		$this->criteria = $criteria;
		if($this->sortField){
			$this->criteria->removeOrder();
			if(strpos($this->sortField, ";") != false){
				$ex = explode(";", $this->sortField);
				foreach( $ex as $field)
					$this->criteria->addOrderBy( $field, $this->sortDir );
			}else{
				$this->criteria->addOrderBy( $this->sortField, $this->sortDir );
			}
		}
	}
	
	public function getCriteria(){
		return $this->criteria;
	}
	
	public function getSort(){
		
	}
	
	public function getOrder(){
		
	}
	
	
	
	public function init(){
		
		$this->debugMode = $this->getProperty("debugMode");
		
		// Filters
		if(isset($_COOKIE[$this->getGlobalId()])) {
			$this->setProperty("filtersRegistry", $_COOKIE[$this->getGlobalId()]);
			
			// TODO obejść - filtry inicjalizują się przed tabelką
			foreach ($this->getAllChildren("ArrowAbstractTableFilter") as $filter ) $filter->init();
		}
		
		$res = ArrowController::$activeProject->getResources();
		//if($this->getProperty("num"))
		//$this->registerJsFile(  "./server/standardModels/org/arrowplatform/controls/presentation/table/resources/jquery.tablednd_0_5.js" );
		$this->registerJsFile( $res->getResource("/js/jquery/jquery.tablednd_0_5.js")->getRelativePath());
		
	//		
			
		
		
			
		if(is_array($this->getProperty("selected")))
			$this->setProperty("selected", implode(";", $this->getProperty("selected")));
		
		$ds = $this->getProperty("dataSource");
		$this->model = $model = $this->getProperty("model");
		$dsFactory = $this->getProperty("dsFactory"); 
		$datasourceCtrl = $this->getFirstChild("ArrowCtrlDatasource");
		
		if( !empty($model)){
			$this->setDataSource( new ArrowDataSource( $model ));	
		}elseif(!empty($ds)){
			$this->setDataSource( $ds );
		}elseif(!empty($datasourceCtrl)){
			$criteria = $datasourceCtrl->getCriteria();
			
			$this->setProperty("model", $criteria->getModel());
			$this->model = $criteria->getModel();
			$this->setDataSource( new ArrowDataSource( $criteria->getModel() ) );
			$this->setCriteria($criteria);
		}elseif(!empty( $dsFactory )){
			$ds = call_user_func( array($this->getPropertyAsModel("dsFactory"), "getNewDataSource") );
			$this->setDataSource( $ds );	
		}else{
			$parent = $this->getParent();
			if( $parent  instanceof IArrowCriteriaUser ){
				$criteria = $parent->getCriteria();
				$this->setCriteria($criteria);
				$model = $criteria->getModel();
				$this->setProperty("model", $model );
				$this->model = $model;
				$this->setDataSource( new ArrowDataSource( $model ));	
			}else{
				throw new ArrowException( array("msg"=> "[ArrowCtrlTable] Datasource needed") );
			}
		}
		
		
		$this->selectable = $this->getProperty("selectable");

		$this->sortable = $this->getProperty("sortable");
		$this->sortField = $this->getProperty("sort");
		
		
		$this->sortDir = $this->getProperty("sortDir");
		
		if( $this->getState("sort-dir")  )
			$this->sortDir = $this->getState("sort-dir");
			
		$this->onPage = $this->getProperty("onPage", "page");
		
		if($this->getProperty("criteria"))
			$this->criteria = $this->getProperty("criteria");
		else
			$this->criteria = new Criteria($model);
			
		if(isset($_SESSION[self::CTRL_NAMESPACE][$this->getGlobalId()]))
			$this->criteria = unserialize($_SESSION[self::CTRL_NAMESPACE][$this->getGlobalId()]);
		
		$columns = $this->getChildren("ArrowAbstractTableColumn");
		if(count($columns ) > 0 ){
			$this->fields = $columns;
			foreach($this->fields as $key => $col){
				if(!$col->getProperty("enabled"))
					unset($this->fields[$key]);
			}
		}else{
			$this->fields = array();
			foreach( $this->dataSource->getFields() as $field ){
				$column = $this->addNode("table", "column", array("name"=>$field->getName(), "field" => $field->getName()));
				$this->fields[] = $column; 
			}
		}
		
		if($this->sortField){
			$this->criteria->removeOrder();
			if(strpos($this->sortField, ";") != false){
				$ex = explode(";", $this->sortField);
				foreach( $ex as $field) {
					$this->criteria->addOrderBy( $field, $this->sortDir );
				}
			}else{
				$this->criteria->addOrderBy( $this->sortField, $this->sortDir );
			}
		}elseif(count($columns ) > 0){
			foreach ( $this->fields as $field ){
				if($sort = $field->getSort())
					$this->criteria->addOrderBy( $field->getName(), $sort );
			}
		}
		
		$ctrlCriteria = $this->getChildren("ArrowCtrlCriteria");
		if( !empty($ctrlCriteria) ){
			$crit = $ctrlCriteria[0]->getCriteria();
			$this->criteria->fromString($crit);
		}
		
		$this->currentPage = $this->getProperty("page");
		
		//Actions configuration
		$ex_model = explode(".", $this->dataSource->getModel()) ;
		$class = @array_pop( $ex_model );
		
		$access = AccessManager::getDefault();
		
		$this->modelActions = $access->getActions($this->getProperty("model"));
		$topGroup = $this->getChildren("ArrowUIActionsGroup");
		$thisId = $this->getProperty("ctrlId");
		foreach( $topGroup as $group){
			$name = $group->getProperty("name");
			if($name == "top"){
				$this->topActions = $group->getActions();
			}elseif ($name == "row")
				$this->rowActions = $group->getActions();
			elseif ($name == "footer")
				$this->footerActions = $group->getActions();	
				
			foreach( $group->getActions() as $action ){
				$action->setProperty("ctrl-connected", $thisId);
			}
		}
		
		$jsData = array(
			"model" => $this->getProperty("model")
		);
		
		$searchCondition = $this->getProperty("searchConditionsBase64");

		$decoded = base64_decode($searchCondition);
		$result = array();
		parse_str($decoded, $result);
			
		$jsData["searchForm"] = (array) $result;
		$jsData["dnd"] = $this->getProperty("num");
		$jsData["globalId"] = $this->getGlobalId();
			
	
		
		
		
		$this->registerJs( get_class($this), dirname(__FILE__)."/resources/ArrowTable.js", ".".self::CTRL_NAMESPACE.'-table-'.$this->getId(), $jsData );
		$this->registerCssFile(  "../server/standardModels/org/arrowplatform/controls/presentation/table/resources/ArrowTable.css");
		
		$searchConf = $this->getChildren("ArrowTableSearch");
		if(!empty($searchConf))
			$this->searchFields[] = $this->addNode("form", "text", array("name" => "table-search", "check" => 0, "value" => urldecode($this->getProperty("search")), "namespace" => 0));
		
		$templates = $this->getChildren("ArrowTableRowTemplate");
		foreach($templates as $template){
			$type = $template->getProperty("type");
			if( $type == "rowExtensionTemplate" ){
				$this->rowExtensibleTemplate = $template;
			}elseif($type == "topTemplate" ){
				$this->searchTemplate = $template;
			}elseif($type == "footerTemplate" ){
				$this->footerTemplate = $template;
			}elseif($type == "lastFooterTemplate" ){
				$this->lastFooterTemplate = $template;
			}elseif($type == "topBasePanel" ){
				$this->topBasePanelTemplate = $template;
			}elseif($type == "topExtendedPanel" ){
				$this->topExtendedPanelTemplate = $template;
			}elseif($type == "grupping" ){
				$this->gruppingTemplate = $template;
			}
		}  
		
		
		$rowClassMap = $this->getChildren("ArrowMapClass");
		foreach($rowClassMap as $map){
			$field = $map->getProperty("field");
			if(empty($field)){
				$this->defautlRowClass = $map->getProperty("class");
			}else{
				$this->rowClassMap[$field][$map->getProperty("value")] = $map->getProperty("class");
			}
		}
	}
	
	public function clearColumns(){
		foreach( $this->getChildren("ArrowAbstractTableColumn") as $column) $this->removeChildren($column);
		$this->fields = array();
	}
	
	public function isSortable(){
		return $this->sortable;
	}
	
	public function getSortField(){
		return $this->sortField;
	}
	
	public function getSortDir(){
		return $this->getState("sort-dir");
	}
	
	public function generateBlockStart(){
		if($this->getProperty("initiated"))
			return $this->generateTable();
		return "";
	}
	
	public function generateBlockEnd(){return "";}
	
	public function generateTable(){
		if($this->getProperty("displaytype") == "table")
			return '<div class="ctrl-table-container">'.$this->generateHead().$this->generateBodyTable()."</div>";
		else
			return $this->generateHead().$this->generateBodyList();
	}
	
	public function generate(){
		if(!$this->getProperty("initiated"))
			return "";
		if($this->getProperty("displaytype") == "table")
			return '<div class="ctrl-table-container">'.$this->generateHead().$this->generateBodyTable()."</div>";
		else
			return $this->generateHead().$this->generateBodyList();
	}
	
	public function generateHead(){
		
		$this->prepareList();
		
		
		$str = '<table class="'.self::CTRL_NAMESPACE.'-table '.self::CTRL_NAMESPACE.'-table-'.$this->getId().' '.$this->getProperty("class").'" style="'.$this->getProperty('style').'" >';
		
		$header = $this->getProperty("header");
		
		$optionsCount = count($this->rowActions);
		$fieldsCount = count($this->fields) + $optionsCount;
		if($this->selectable) $fieldsCount++;
		if($this->rowExtensibleTemplate) $fieldsCount++;
		if($this->getProperty("num")) $fieldsCount++;
		
		
		if($header){
		
		
		$str.= '<thead class="ctrl-table-head">'; 
		
		
		
		foreach($this->fields as $field)
			if($field->getProperty("width") == -1)
				$fieldsCount--;
		
		$top = "";
		if($title = $this->getProperty("title"))
			$top.= '<div class="ctrl-table-title">'.$title.'</div>';
			
		if($this->debugMode){
			$str.= '<tr><td colspan="'.$fieldsCount.'" class="ctrl-table-top" >';
			$str.= $this->generateDebugView()."</td></tr>";
		}
		
		
			
		$top.= $this->generateTopActions();
		
		$layout = $this->getProperty("layout");
		
		$topPanel = "";
		if($layout == "compact"){
			$topPanel = $top;
		}else if( !empty($top) ){
			$str.= '<tr><td colspan="'.$fieldsCount.'" class="ctrl-table-top" >';
			$str.= $top."</td></tr>";
			
		}
		
		
		
		if($this->searchFields != null){
			foreach($this->searchFields as $field)
				$topPanel.= '<div class="ctrl-table-quick-search"><table><tr><td>'.$field->generate().'</td><td> <input type="button" value="Szukaj"/></td></tr></table></div>';
		}
		if($this->topBasePanelTemplate != null){
			$topPanel.= '<div style="padding:3px; float: left;">'.$this->topBasePanelTemplate->generateTemplate()."</div>";
		}
		
		if($this->onPage != false)
			$topPanel.= $this->generatePaging();
			
		
		
		if(!empty($topPanel)){
			$str.= '<tr><td colspan="'.$fieldsCount.'" class="ctrl-table-top ctrl-table-top-panel" ><div class="ctrl-table-panel ">';
			$str.= $topPanel.'<div style="clear:both;"></div></div></td></tr>';
		}
		
		
		}
		
		
		
		if($this->searchTemplate != null){
			$expanded = $this->getProperty("searchAreaExpanded")?'style="display:block"':'';
			//'.$expanded.'
			$str.= '<tr class="ctrl-table-search-area-row"><td colspan="'.$fieldsCount.'" class="ctrl-table-search-area-td" >';
			$str.= '<a href="" class="ctrl-table-seach-area-trigger">&nbsp;</a>';
			$str.= '<div class="ctrl-table-search-area-content" '.$expanded.'>';
			$str.= $this->searchTemplate->generate();
			$str.= "</div></td></tr>"; 
		}
		
		/*if($this->onPage != false){
			$str.= '<tr><td colspan="'.$fieldsCount.'" class="ctrl-table-paging-row" >';
			$str.= $this->generatePaging()."</td></tr>";
		}*/
		
		$row3 = '';
		$row2 = "<tr class=\"ctrl-table-header-separator\"  >";
		$str.= "<tr class=\"ctrl-table-header\" >"; 
		
		if($this->selectable){
			$str.='<th style="width: 15px;"><input type="checkbox" class="'.self::CTRL_NAMESPACE.'-table-check-all" /></th>';
			$row2.='<th style="width: 15px;"></th>';
		}
		
		if($this->rowExtensibleTemplate){
			$str.='<th style="width: 15px;"></th>';
			$row2.='<th style="width: 15px;"></th>';
		}
			
		if($this->getProperty("num")){
			$link = $this->getStateChangeLink(array("sort" => "sort"));
			$str.='<th style="width: 30px;"><a href="'.$link.'" class="ctrl-table-sort-header" >&nbsp;</a></th>';
			$row2.='<th style="width: 30px;"></th>';
		}
		
		$am = AccessManager::getDefault();
		foreach( $this->fields as $field ){
      		//if( $am->checkColumn( $this->getProperty("model"), $field ,1 ) ) { 
        	$str.= $field->generateHeader();
        	$row3.=$field->generateSetFilters();
        	$row2.='<th></th>';
			//}
		}
		$row3.=$this->generateExternalFilters();
		if($optionsCount > 0){
			$str.='<th colspan="'.$optionsCount.'">Opcje</th>';
			$row2.='<th colspan="'.$optionsCount.'" ></th>';
		}
		
		$str.= "</tr>";
		$row2.= "</tr>";
		
		if(empty($row3))
			$display  = 'display: none;';
		else
			$display = '';
			
		if(isset($_COOKIE[$this->getGlobalId()]))
			$tmp = 'checked="checked"';
		else
			$tmp = '';
			
		$tmp = '<div>zapamiętaj <input class="ctrl-table-filters-save" type="checkbox" '.$tmp.'/></div><div class="ctrl-table-remove-all-filters"></div>';
		if( !empty( $row3 ) ) {
			$row3 = '<div style="width: 90%;"><div>Zastosowane filtry: </div>'.$row3.'</div>'.$tmp;
			$row3 = '<th colspan="'.$fieldsCount.'">'.$row3.'</th>';
			$row3 = '<tr style="'.$display.'" class="ctrl-table-header-set-filters" >'.$row3.'</tr>';
		}
		
		$str.=$row2;
		$str.=$row3;
		$str.= "</thead>";
		
		return $str;
	}
	
	private function generateDebugView(){
		
		$str = "";
		$str.= "<h4>Query</h4><pre>".$this->debugData["query"]."</pre>";
		$str.= "<h4>Time</h4>".$this->debugData["timeQuery"];
		$str.= "<h4>Explain</h4><table><tr>";
		foreach( array_keys($this->debugData["explainQuery"][0]) as $key )
			$str.="<td>".$key."</td>";
		$str.="</tr>";
		foreach($this->debugData["explainQuery"] as $el){
			$str.= "<tr>";
			foreach($el as $i){
				$str.="<td>".$i."</td>";
			}
			$str.="</tr>";
		}
		$str.="</table>";
		
		$str.= "<h4>Query count</h4><pre>".$this->debugData["queryCount"]."</pre>";
		$str.= "<h4>Time</h4>".$this->debugData["timeCount"];
		$str.= "<h4>Explain</h4><table><tr>";
		foreach( array_keys($this->debugData["explainCount"][0]) as $key )
			$str.="<td>".$key."</td>";
		$str.="</tr>";
		foreach($this->debugData["explainCount"] as $el){
			$str.= "<tr>";
			foreach($el as $i){
				$str.="<td>".$i."</td>";
			}
			$str.="</tr>";
		}
		$str.="</table>";
		
		
		return $str;
	}
	
	private function generateExternalFilters(){
		$registry = json_decode( base64_decode($this->getState("filtersRegistry")), true);
		$str = "";
		if(is_array($registry)){
			foreach(  $registry as $field => $val ){
				if(isset($val["title"])){
					$title = $val["title"];
					$value = htmlspecialchars($val['value']);
					
					if(!empty($value)) {
						$tmpRegistry = $registry;
						unset($tmpRegistry[$field]);
						$encoded = base64_encode(json_encode($tmpRegistry));
						$link = ArrowCtrlStateManager::getDefault()->getStateChangeLink($this, array( "filtersRegistry" => $encoded ));
						
						if(isset($val["label"]) && $val["label"]) $value = $val["label"];
						$generate_value  = "<div class=\"ctrl-table-set-filter-value\" >$value</div><a rel=\"{$encoded}\" href=\"{$link}\" ></a>";
						$str.= '<div class="ctrl-table-set-filter" >';
						$str.= '<div>'.$title.':</div>'.$generate_value;
						$str.= '</div>';
					}
				}
			}
		}
			
		return $str; 
		
	}
	
	public function prepareList(){
		
		if($this->onPage)
			$this->criteria->setLimit( $this->currentPage * $this->onPage, $this->onPage);
			
			
		
		if( $this->getProperty("clearCriteria")  ){
			if(!is_object($this->criteria)){
				
			}
			$this->criteria->setEmptyList(); 
			foreach( $this->fields as $field ){
				$alias = $field->getProperty("alias");
				if( $alias === false ) $alias = '' ;
				$sqlFunction = $field->getProperty("sqlFunction");
				if( $sqlFunction === false ) $sqlFunction = '' ;
				$field = $field->getField();
		        if(strpos($field, ";") != false){
		          $ex = explode(";", $field);	
		          if( $alias != false || $sqlFunction != false ) throw ArrowException( "Niemożna używać aliasów oraz funkcji dla wielu pól w kolumnach" );
		          foreach( $ex as $_field) {
		          	$this->criteria->addColumn( $_field );
		          }
		        }else{
		          $this->criteria->addColumn($field, $alias, $sqlFunction );
		        }
			}
		}
		
		try {
			$conf = Persistent::getClassConf(ArrowModel::getModelClass($this->getProperty("model")));
			if(isset($conf["field"]["_state"]) )
      			$this->criteria->addColumn("_state");
		} catch (Exception $ex){}
		
		$registry = $this->getProperty("filtersRegistry");
		$delegate = $this->getProperty("beforeFiltersDelegate");
		
		$registry = (array) json_decode(base64_decode($registry), true);
		
		
		if(isset($registry["ctrlTableSearchConditions"])){
			$searchSet = $this->getChildren("ArrowTableSearch");
			$fields = $searchSet[0]->getProperty("fields");
			$fields = explode(";", $fields);
			
			$conditionType =  $searchSet[0]->getProperty("conditionType");
			if($conditionType == Criteria::C_LIKE)
				$search = "%".$registry["ctrlTableSearchConditions"]["value"]."%";
	
			$this->criteria->addSearchCondition($fields, $search, $conditionType);
		}
		
		
		
		if($delegate){
			$obj = ArrowView::getCurrentView();
			call_user_func_array( array($obj, $delegate), array( &$this->criteria, &$registry ) );
		}		
		
		if(!empty($registry)){
			
			$model = explode('.', $this->getProperty("model"));
			$model = end($model);
			$table_to_alias = array();
			foreach($registry as $field => $val){
				
				// multi-column filters
				$multi_field = explode(";", $field);
				$conditions = array();
				
				foreach($multi_field as $field_item) {
					$test = explode(":", $field_item);
					
					if(count($test) > 1) {
						$class = $test[0];
						$class = explode( '[', $class );
						$class = $class[0] ; 
						$field_item = end( $test );
					} else
						$class = $model;
	
					$criteria = new Criteria($class);
					if(array_key_exists('process', $val) && $val['process']) {
						if(strpos($val['value'], "_arrow_range_") !== false) {
							$tmp = explode("_arrow_range_", $val['value']);
							if((!empty($tmp[0]) && is_numeric($tmp[0])) || (!empty($tmp[1]) && is_numeric($tmp[1]))) {
								$criteria->startGroup(ArrowOrmCriteria::C_AND_GROUP);
								if(!empty($tmp[0]) && is_numeric($tmp[0]))
									$criteria->addCondition( $field_item, $tmp[0], Criteria::C_GREATER_EQUAL );
								if(!empty($tmp[1]) && is_numeric($tmp[1]))
									$criteria->addCondition( $field_item, $tmp[1], Criteria::C_LESS_EQUAL );
								$criteria->endGroup();
							}
						} else if(strpos($val['value'], "_arrow_sep_") !== false){
							$tmp = explode("_arrow_sep_", $val['value']);
							if( $tmp[0] != "__---__" ) {
								if(is_numeric($tmp[0]))
									$criteria->addCondition( $field_item, (int)$tmp[0] );
								else
									$criteria->addCondition( $field_item, $tmp[0] );
							}
							$flag = false;
						}else if(strpos($val['value'], "_arrow_date_") !== false){
							$tmp = explode("_arrow_date_", $val['value']);
							if(!empty($tmp[0]) || !empty($tmp[1])) {
								$criteria->startGroup(ArrowOrmCriteria::C_AND_GROUP);
								if(!empty($tmp[0]))
									$criteria->addCondition( $field_item, date('Y-m-d 00:00:00', strtotime($tmp[0])), Criteria::C_GREATER_EQUAL );
								if(!empty($tmp[1]))
									$criteria->addCondition( $field_item, date('Y-m-d 23:59:59', strtotime($tmp[1])), Criteria::C_LESS_EQUAL );
								$criteria->endGroup();
							}
						} else {
							if(is_array($val) && array_key_exists('value', $val)) {
								$val['value'] = str_replace("arrow_zero", 0, $val['value']);
								
								if(array_key_exists('strict', $val) && !$val['strict']) {
									$val['value'] = "%".$val['value']."%";
									$criteria->addCondition( $field_item, $val['value'], Criteria::C_LIKE );
								}
								else if(!empty($val['value'])) {
									$criteria->addCondition( $field_item, $val['value'] );
								}
							}
						}
					}
					$conf = (ArrowOrmConfig::getClassConf($class));
					$table_to_alias[$conf['attr']['table']] = $conf['attr']['table'] ;
					$conditions[] = ArrowOrmSqlRouter::conditionsToSql($criteria, $conf['attr']['db']);
					//print_r( $criteria );
					//print_r( ArrowOrmSqlRouter::conditionsToSql($criteria, $conf['attr']['db']) );
					//exit;
				}
				
				$str = '';
				foreach($conditions as $condition)
					$str .= " $condition ||";
				
				$str = ' ('.trim($str, '||').') ';
				$this->criteria->addCustomCondition($str, $table_to_alias);
			}
		}
		
		
		$countDelegate = $this->getProperty("countDelegate");
		
		
		if($this->debugMode){
			
			$time_start = microtime(true);
			$this->list = $this->dataSource->getList($this->criteria);
			$time_end = microtime(true);
			$timeQuery = $time_end - $time_start;
			$q = ArrowOrmMysql::getLastQuery();
			
			$time_start = microtime(true);
			
			if($countDelegate){
				$this->allRowsCount = call_user_func(array(ArrowView::getCurrentView(), $countDelegate),  $this->criteria);
			}else{
				$this->allRowsCount = $this->dataSource->countList( $this->criteria );
			}
			$time_end = microtime(true);
			$timeCount = $time_end - $time_start;
			$qCount = ArrowOrmMysql::getLastQuery();
			
			
			
			$this->debugData = array(
				"query" => $q,
				"timeQuery" => $timeQuery,
				"explainQuery" => ArrowOrmSqlRouter::toArray(ArrowOrmSqlRouter::query("EXPLAIN ".$q)),
				"queryCount" => $qCount,
				"timeCount" => $timeCount,
				"explainCount" => ArrowOrmSqlRouter::toArray(ArrowOrmSqlRouter::query("EXPLAIN ".$qCount))
			);
			
		}else{
			$this->list = $this->dataSource->getList($this->criteria);	
			if($countDelegate){
				$this->allRowsCount = call_user_func(array(ArrowView::getCurrentView(), $countDelegate),  $this->criteria);
			}else{
				$this->allRowsCount = $this->dataSource->countList( $this->criteria );
			}
		}
		
		$processMethod = $this->getProperty("processResult");
		if($processMethod){
			$obj = ArrowView::getCurrentView();
			call_user_func( array($obj, $processMethod), $this->list );
		} 
		
				
		
	}
	
	public function generateBodyTable(){
		
		$zebra = $this->getProperty("zebra");
		$grupping = $this->getProperty("grupping");
		
		$zebra = ($zebra=="1")?true:false;
		$str="<tbody>";
		
		$rowTemplates = $this->getChildren("ArrowTableRowTemplate");
		$rowTemplate = false;
		foreach($rowTemplates as $template)
			if($template->getProperty("type") == "rowTemplate")
				$rowTemplate = $Template->getContentCode();
		

		$groupField = "UtilsDictionary[Task::id_priority]:name";
		$groupField = $this->getProperty("sort");
		if(strpos($groupField, ";" ) !== false ){
			$groupField = explode(";",$groupField);
			$groupField = $groupField[0];
		}
		$gruppingValue = null;
		
		if(empty($this->list )){
			$str.='<tr><td colspan="20" align="center">Brak wpisów</td></tr>';	
		}
		
		$num = $this->getProperty("num");
		$selected = explode( ";", $this->getProperty("selected"));
		$model = $this->getProperty("model");
		if($this->rowExtensibleTemplate)
			$triggerColumn =  $this->rowExtensibleTemplate->getTriggerColumn();

		$get_class_delegate = $this->getProperty("getRowClassDelegate");
		$thisCtrlId = $this->getProperty("ctrlId");
		foreach( $this->list as $key => $obj ){
			
			if($grupping && $groupField && $obj->getValue($groupField) != $gruppingValue){
				$gruppingValue = $obj->getValue($groupField);
				$addData = array("gruppingField" => $groupField, "gruppingValue" => $gruppingValue);
				$str.="<tr class=\"ctrl-table-grupping-row\"><td colspan=\"20\">".$this->parseRowTemplate( $this->gruppingTemplate->getContentCode(), $obj, $addData)."</td></tr>";
				
			}
			
			if($rowTemplate){
				$str.=$this->parseRowTemplate($rowTemplate, $obj);
				continue;
			}
			
	
			$rowClass = "";
			if(!empty($this->rowClassMap)){
				foreach($this->rowClassMap as $field => $val){
					if(isset($this->rowClassMap[$field][$obj[$field]]))
						$rowClass = $this->rowClassMap[$field][$obj[$field]];
				}
			}
			if(!$rowClass && $this->defautlRowClass)
				$rowClass = $this->defautlRowClass;

			
			$own_class = "" ;
			if($get_class_delegate){
				$vobj = ArrowView::getCurrentView();
				$own_class = " ".call_user_func( array($vobj, $get_class_delegate), $obj );
			} 
			
			$str.= "<tr ".(($key%2&&$zebra&&$key!=0)?'class="even '.$rowClass.$own_class.'"':'class="'.$rowClass.$own_class.'"')." id=\"ctrl-row-{$obj->getPKey()}\" >";
			
			if($this->selectable){
				$key1 = $obj->getPKey();
				$checked = (in_array($key1, $selected))?'checked="checked"':'';
				$str.='<td><input type="checkbox" class="'.self::CTRL_NAMESPACE.'-table-check" name="'.self::CTRL_NAMESPACE.'-'.$thisCtrlId.'" '.$checked.' value="'.$key1.'" /></td>';
			}
			
			if($this->rowExtensibleTemplate){
				$link = "";
				$link = $this->rowExtensibleTemplate->getStateChangeLink(array("model" => $model, "key" => $obj->getPKey()), true);
				if( !$triggerColumn || ($triggerColumn && $obj[$triggerColumn]) ) 
					$str.='<td><a class="ctrl-table-extenible-row" href="'.$link.'">&nbsp;</a></td>';
				else
					$str.='<td></td>';
			}
			
			
			
			
			if($num){
				if(strpos($this->sortField, "sort") !== false)
					$str.='<td class="ctrl-table-num" model="'.$model.'" >'.(($key+1) + $this->currentPage * $this->onPage).'</td>';
				else
					$str.='<td class="ctrl-table-num">--</td>';
			}
			
			foreach( $this->fields as $field ){
        //if( $am->checkColumn( $this->getProperty("model"), $field ,1 ) ) {        
          $str.= $field->generateCell( $obj );
				//}
			}
			$str.= $this->generateObjectActions( $obj );
			
			$str.= "</tr>";	
		}
		$str.="</tbody>";
		
		$str.=$this->generateFoot();	
		$str.= "</table>"; 
		
		$name = $this->getProperty("name");
		if(!empty($name))
			$str.=$this->addNode("form", "hidden", array(
				"name" => $name, 
				"value" => $this->getProperty("selected"),
				"class" => "ctrl-table-hidden-field"
			))->generate();
		
		
		return $str; 
	}
	
	private function generateBodyList(){
		$str = "</table>";
		$str.= '<div class="ctrl-table-list-container">';
		
		//$this->prepareList();
		
		$cellTemplate = $this->getChildren("ArrowTableCellTemplate");
		if(isset($cellTemplate[0]))
			$cellTemplate = $cellTemplate[0]->getContentCode();
		else
			$cellTemplate = false;
		
		
		foreach( $this->list as $key => $obj ){
			$str.= '<div class="ctrl-table-list-cell">';
			$str.=$this->parseRowTemplate($cellTemplate, $obj);
			$str.='<table class="ctrl-table-list-actions"><tr>'.$this->generateObjectActions( $obj ).'</td></tr></table>';
			$str.="</div>";
		}
		$str.= '<div style="clear:both;"></div>';
		$str.=$this->generateFoot();	
		$str.= "</div>";
		return $str;
		
	}
	
	private $smartyCompiler;
	private function parseRowTemplate( $template, $obj, $addData = array() ){
		
		if($this->smartyCompiler == null)
			$this->smartyCompiler = new SmartyCompiler($template);
		$this->smartyCompiler->assign("context", $obj);
		$this->smartyCompiler->assign("additionalData", $addData);
		return $this->smartyCompiler->getResult(array());
		
		/*
		foreach( $obj as $field => $value ){
			$template = str_replace( "#".$field."#", $value, $template );
		}
		ob_start();
		eval('?'.'>' . $template );
		$c = ob_get_contents(); 
		ob_clean();*/
		//return $c;
	}
	
	private function generateTopActions(){
		$access = AccessManager::getDefault();
		$content = "";
		if(!empty( $this->topActions ) ){
			foreach( $this->topActions as $action ){
				if($action->getProperty("type") == "execute")
					$action->setProperty("model", $this->model);
				if($access->check($this->model, $action->getId(), true))
					$content.= '<div class="ctrl-toolbar-element">'.$action->generate( )."</div>";
			}
			$content = trim($content, " |");
		}elseif($this->getProperty("showModelActions")){
			foreach( $this->modelActions as $action ){
				if($action->getType()==IArrowModelAction::STATIC_ACTION )
					$content.= $action->getId()."[Allowed: '".($action->isAllowed()?'yes':'no')."'], ";
			}
		}
		if(!empty($content))
			return '<div class="'.self::CTRL_NAMESPACE.'-table-list-actions ctrl-toolbar ctrl-top-toolbar">'.$content."</div>";
		return "";
	}
	
	private function generateFooterActions(){
		$access = AccessManager::getDefault();
		$content = "";
		if(!empty( $this->footerActions ) ){
			foreach( $this->footerActions as $action ){
				if($action->getProperty("type") == "execute")
					$action->setProperty("model", $this->model);
				if($access->check($this->model, $action->getId(), true))
					$content.= '<div class="ctrl-toolbar-element">'.$action->generate( )."</div>";
			}
			$content = trim($content, " |");
		}
		if(!empty($content))
			return '<div class="'.self::CTRL_NAMESPACE.'-table-list-actions  ctrl-footer-toolbar">'.$content."</div>";
		return "";
	}
	
	
	protected function generateObjectActions( IArrowControlable $object){
		$str = "";
		$access = AccessManager::getDefault();
		if(!empty( $this->rowActions ) ){
			foreach( $this->rowActions as $action ){
				if($access->check( $object, $action->getId(), true))
					$str.= '<td>'.$action->generate( $object ).'</td>';
				elseif($action->getProperty("checkAccess") == "0")
					$str.= '<td>'.$action->generate(  $object).'</td>';
				else
					$str.= '<td></td>';
			}
		}elseif($this->getProperty("showModelActions")){
			foreach( $this->modelActions as $action ){
				if($action->getType()==IArrowModelAction::OBJECT_ACTION)
					$str.= '<td>'.$action->getId()."[Allowed: '".($action->isAllowed()?'yes':'no')."'], ".'</td>';
			}
		}
		return $str;
	}
	private function generateFoot(){
		$str = "" ;
		$displayType  = $this->getProperty("displaytype") ;
		$optionsCount = count($this->rowActions);
		$fieldsCount = count($this->fields) + $optionsCount;
		if($this->selectable) $fieldsCount++;
		if($this->rowExtensibleTemplate) $fieldsCount++;
		if($this->getProperty("num")) $fieldsCount++;
		if($this->footerTemplate != null || $this->lastFooterTemplate != null || $this->getProperty("footer") ) {
			if( $displayType == "table" ) 
				$str .= '<tfoot>' ;
			else 
				$str .= '<div align="right">';
				
			if($this->footerTemplate != null){
				if( $displayType == "table" ){ 
					$str.= '<tr class="ctrl-table-footer-area-row">';
					$str.= '<td colspan="'.$fieldsCount.'" class="ctrl-table-footer-area-td" >';
				}
				$str.= '<div class="ctrl-table-footer-area-content" >';
				$str.= $this->footerTemplate->generate();
				$str.= "</div>" ;
				if( $displayType == "table" ) 
					$str .=	"</td></tr>"; 
			}	
			
			if($this->getProperty("footer")){
				if( $displayType == "table" ){
					$str .= '<tr>';
					if($this->selectable){
						$str.= '<td class="ctrl-footer-mass" >&nbsp;</td>';
					}
					$str .= '<td align="right" colspan="'.$fieldsCount.'" >';
					
				}
				
					
				
				$str.= "<div class=\"right\"> Wszystkich: <b class=\"ctrl-table-rows-count\">". $this->allRowsCount."</b></div>";
				
				$str.= $this->generatePaging(true);
				
				$str.="<div class=\"right\">Pokaż ";
				$str.='<select onchange="window.location.href = this.options[this.selectedIndex].value;">';
				for( $i=25;$i<=100; $i+=25  ){
					$href = $this->getStateChangeLink( array( "onPage" => $i, "page" => 0) );
					$str.="<option value=\"$href\" ".(($i==$this->onPage)?'selected="selected"':'')." >".$i."</option>";
				}
				$str.="</select></div>";
				
				
				
				if( $displayType == "table" ){
					
					$str.= "</td></tr>";
					if($this->selectable){
						$footerActions = $this->generateFooterActions() ;
						$str.='<tr><td class="ctrl-footer-mass-bottom" colspan="'.++$fieldsCount.'"><b style="float:left;">Zaznaczone:</b> '.$footerActions.'</td></tr>';
					}
				}
				
				
			}
			
			/*
			if( $footerActions != "" ) {
				if( $displayType == "table" ) 
					$str.= '<tr class="ctrl-table-footer-actions"><td colspan="'.$fieldsCount.'" class="ctrl-table-footer-area-td" ><table><tr><th>Zaznaczone:</th><td colspan="'.($fieldsCount-1).'" class="ctrl-table-footer-area-td" >';
					$str .= $footerActions ;
					if( $displayType == "table" ) 
						$str .=	"</tr></table></td></tr>"; 
			}*/
			
			if($this->lastFooterTemplate != null){
				if( $displayType == "table" ) 
					$str.= '<tr class="ctrl-table-last-footer-area-row"><td colspan="'.$fieldsCount.'" class="ctrl-table-last-footer-area-td" >';
				$str.= '<div class="ctrl-table-last-footer-area-content" >';
				$str.= $this->lastFooterTemplate->generate();
				$str.= "</div>" ;
				if( $displayType == "table" ) 
					$str .=	"</td></tr>"; 
			}
			
			if( $displayType == "table" )
				$str.= "</tfoot>";
			else
				$str.= "</div>";
		}
		
		return $str;
	}
	
	private function generatePaging($forFoot = false){
		$str = '<div class="'.self::CTRL_NAMESPACE.'-table-paging">';
		
		
		$str.= '<a class="ctrl-table-refresh" href="'.$this->getStateChangeLink(array()).'">&nbsp;</a>';
		
		$all = $this->allRowsCount;
		
		if($all/$this->onPage > 1){
		
			
			$url = $_SERVER["REQUEST_URI"];
			
			if( $this->currentPage > 0){
				$href = $this->getStateChangeLink( array( "page" => 0) );
				$str.='<a href="'.$href.'" class="arrow-left-all">&nbsp;</a> ';
				$href = $this->getStateChangeLink( array( "page" => $this->currentPage - 1) );
				$str.='<a href="'.$href.'" class="arrow-left">&nbsp;</a> ';
			}
			
			$ceil = ceil($all/$this->onPage-1);
			
			if($forFoot){
				if($all/$this->onPage > 1){
					$str.="Strona ";
					$str.='<select onchange="window.location.href = this.options[this.selectedIndex].value;">';
					$ceil = ceil($this->allRowsCount/$this->onPage-1);
					$href = $this->getStateChangeLink( array( "page" => "__page__") );
					for( $page=0;$page<=$ceil; $page++  ){
						$currHref = str_replace("__page__", $page, $href);
						$str.="<option value=\"$currHref\" ".(($page==$this->currentPage)?'selected="selected"':'')." >".($page+1)."</option>";
					}
					$str.="</select>";
				}
				
			}else{	
				for( $page= $this->currentPage-6;$page<$this->currentPage+6; $page++  ){
					if($page >= 0 && $page <= $ceil){
						if( $page == $this->currentPage ){
							$str.="<b>[ ".($page+1)." ]</b> ";
						}else{
							$href = $this->getStateChangeLink( array( "page" => $page) );
							$str.="<a href=\"$href\"  >".($page+1)."</a> ";
						}
					}
				}
			}
			if( $this->currentPage < $all/$this->onPage - 1){
				$href = $this->getStateChangeLink( array( "page" => $this->currentPage + 1) );
				$str.=' <a href="'.$href.'" class="arrow-right">&nbsp;</a> ';
				$href = $this->getStateChangeLink( array( "page" => $ceil) );
				$str.=' <a href="'.$href.'" class="arrow-right-all">&nbsp;</a> ';
				
				
			}
			
		}
		//Dodaj przycisk Eksport CSV
		$exports = $this->getChildren("ArrowTableExport");
		if (!empty($exports)){
      foreach($exports as $export)
      $str.= $export->generateBlockEnd();
		}
		//------------------------------
		$str.="</div>";
		return $str;
	}

	public function refreshInit( ) {
		$columns = $this->getChildren("ArrowAbstractTableColumn");
		if(count($columns ) > 0 ){
			$this->fields = $columns;
			foreach($this->fields as $key => $col){
				if(!$col->getProperty("enabled"))
					unset($this->fields[$key]);
			}
		}
		
		
	}
}
?>
